/**
 * 
 */
package com.googlecode.xcarve.netty.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.xcarve.object.RPCReponse;
import com.googlecode.xcarve.object.RPCRequest;

/**
 * @author xinyun.d
 * 2014年9月21日
 */
public class JdkProxy implements ProxyFactory{
	static final Logger logger = LoggerFactory.getLogger(JdkProxy.class);
	
	private CarveTemplate template;
	
	/**
	 * @param template
	 */
	public JdkProxy(CarveTemplate template) {
		super();
		this.template = template;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T getProxy(final Class<?> interfaces) {
		return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{interfaces}, new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				String methodName = method.getName();
			    Class<?>[] parameterTypes = method.getParameterTypes();
		        if ("toString".equals(methodName) && parameterTypes.length == 0) {
		            return interfaces.getClass().getName()+"&Proxy0";
		        }else if("equals".equals(methodName)){
		        	return true;
		        }
				RPCRequest request = new RPCRequest();
				request.setService(interfaces);
				request.setArguments(args);
				request.setMethodName(methodName);
				request.setParameterTypes(parameterTypes);
				RPCReponse response = template.request(request);
				if(logger.isDebugEnabled()){
					logger.debug("xcarve rpc return response = {}",response);
				}
				if(!response.isStatus()){
					logger.error("this message from remote server,errorMessage={}", response.getMessage());
					throw new RuntimeException("this message from remote server,errorMessage="+response.getMessage());
				}
				return response.getResult();
			}
		}/* new JDKInvacation(interfaces)*/);
	}
	
	class JDKInvacation implements InvocationHandler{
		private Class<?> service;
		
		/**
		 * @param service
		 */
		public JDKInvacation(Class<?> service) {
			super();
			this.service = service;
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			String methodName = method.getName();
		    Class<?>[] parameterTypes = method.getParameterTypes();
	        if ("toString".equals(methodName) && parameterTypes.length == 0) {
	            return "TtoStringMethod&Proxy0";
	        }
			RPCRequest request = new RPCRequest();
			request.setService(service);
			request.setArguments(args);
			request.setMethodName(methodName);
			request.setParameterTypes(method.getParameterTypes());
			RPCReponse response = template.request(request);
			return response.getResult();
		}
		
	}
	
}
